using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Taxhui.Utils.Network.Delegate;
using Taxhui.Utils.Network.Tcp.Awaitable;
using Taxhui.Utils.Network.Tcp.NetSession;
using Taxhui.Utils.Network.Tcp.TcpConfig;
using System.Threading.Tasks;
using Taxhui.Utils.Network.CustomProc;

namespace Taxhui.Utils.Network.Tcp
{
    /// <summary>
    /// 服务器代理
    /// </summary>
    public class ServerAgent : NetEngineBased, IDisposable
    {
        Socket _listener; //socket对象
        bool _isruning = true; //运行标志
        ServerConfig _config; //服务器配置项
        private SessionType _sessionType = SessionType.Full; //会话模式，默认FULL
        #region 构造函数
        internal ServerAgent(
            SessionType sessionType,
            ServerConfig cfg,
            NotifyEventHandler<CompleteNotify, Session> notify,
            ICustomDataProc hdProc=null)
            : base(sessionType, cfg, notify,hdProc)
        {
            _config = cfg;
            _sessionType = sessionType;
            //包模式下开启了应用保持在线则启动检测线程
            
                Task.Run(AliveCheck);
        }
        #endregion
        #region 当前Agent绑定的EndPoint
        public IPEndPoint LocalEndPoint
        {
            get { return (IPEndPoint)_listener.LocalEndPoint; }
        }
        #endregion
        #region 会话超时检测线程
        private void AliveCheck()
        {
            while (_isruning)
            {

                for (int i = 0; i < _sessions.Count; i++)
                {
                    var session = (PackSessionBased)_sessions[i];
                    if (session.State != ConnectionState.Connected)
                    {
                        _logger.WriteLog("心跳，当前会话未连接");
                        _sessions.RemoveAt(i); i--;
                        continue;
                    }
                    if (_config.AutoHeartBeat && _sessionType == SessionType.Packet)
                    {  
                        //距离上次活动时间超过了20秒，已经超时
                        if ((int)(DateTime.Now - session.HeartTime).TotalSeconds > 20)
                        {
                            _logger.WriteLog("Alive超时 --会话状态：" + session.State.ToString() + " 当前时间：" + DateTime.Now.ToString() + " 上次活动时间：" + session.HeartTime.ToString());
                            if (session.State == ConnectionState.Connected)
                            {
                                Console.WriteLine("会话超时，关闭");
                                session.Close(true);
                                _sessions.RemoveAt(i); i--;
                            }
                        }
                    }
                }
                Thread.Sleep(5000);
            }
        }
        #endregion
        #region 启动服务器
        public void Listen(string ip, int port)
        {
            IPAddress ipAddr = null;
            IPAddress.TryParse(ip,out ipAddr);
            if (null == ipAddr)
                throw new ArgumentException("无法解析的IP地址");
            IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port);
            Listen(ep);
        }
        public void Listen(IPEndPoint ep)
        {
            _isruning = true;
            _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //绝对独占，不允许复用
            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, true);
            //_listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            _listener.Bind(ep);
            _listener.Listen(_config.PendingConnectionBacklog);
            var awaiter = _awaiterPool.Take();
            NetHelper.AcceptAsync(_listener, awaiter, AcceptCallback);//socket,awaiter,回调函数
        }
        #endregion
        #region 新连接
        private void AcceptCallback(Awaiter awaiter, SocketError socketError)
        {
            if (socketError == SocketError.Success)
            {
                var acceptedSocket = awaiter.Args.AcceptSocket;
                var session = _sessionPool.Take();
                session.Attach(acceptedSocket);
                _sessions.Add(session);
                //新连接事件
                _completetionNotify?.Invoke(CompleteNotify.OnConnected, session);
                //开始接收数据
                session.StartProcess();
            }
            else _logger.WriteLog("接受请求失败,消息：" + socketError.ToString());
            //服务器已停止时直接返回
            if (!_isruning) return;
            //清除状态，继续接收新客户端
            awaiter.Args.AcceptSocket = null;
            NetHelper.AcceptAsync(_listener, awaiter, AcceptCallback);
        }
        #endregion
        #region 广播
        public override void Broadcast(byte[] data)
        {
            Broadcast(data, 0, data.Length);
        }
        public override void Broadcast(byte[] data, int offset, int length)
        {
            if (_sessionType == SessionType.Full)
            {
                foreach (FullSessionBased session in _sessions)
                    session.SendAsync(data, offset, length);
            }
            else
            {
                foreach (PackSessionBased session in _sessions)
                    session.SendAsync(data, offset, length);
            }
        }
        #endregion
        #region 断开所有客户端
        public override void ClearConnections(bool notify)
        {
            foreach (Session session in _sessions)
                session.Close(notify);

            _sessions.Clear();
        }
        #endregion
        #region 析构函数
        public override void Dispose()
        {
            try
            {
                _listener.Close(0);
                _listener = null;
            }
            catch (Exception e)
            {
                _logger.WriteLog("关闭服务器 异常信息：" + e.Message);
            }

            _logger.Dispose();
            _isruning = false;
            ClearConnections(false);
            _awaiterPool.Dispose();
            _sessionPool.Dispose();
        }
        #endregion
    }
}
